package io.kiki.stack.http.feign.reactive;

import feign.Feign;
import feign.InvocationHandlerFactory;
import feign.Target;
import reactor.core.scheduler.Scheduler;
import reactor.core.scheduler.Schedulers;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.Map;

public class ReactorFeign extends ReactiveFeign {

    public static Builder builder() {
        return new Builder(Schedulers.boundedElastic());
    }

    public static Builder builder(Scheduler scheduler) {
        return new Builder(scheduler);
    }

    public static class Builder extends ReactiveFeign.Builder {

        private final Scheduler scheduler;

        Builder(Scheduler scheduler) {
            this.scheduler = scheduler;
        }

        @Override
        public Feign internalBuild() {
            super.invocationHandlerFactory(new ReactorInvocationHandlerFactory(scheduler));
            return super.internalBuild();
        }

        @Override
        public Builder invocationHandlerFactory(InvocationHandlerFactory invocationHandlerFactory) {
            throw new UnsupportedOperationException("Invocation Handler Factory overrides are not supported.");
        }
    }

    private static class ReactorInvocationHandlerFactory implements InvocationHandlerFactory {
        private final Scheduler scheduler;

        private ReactorInvocationHandlerFactory(Scheduler scheduler) {
            this.scheduler = scheduler;
        }

        @Override
        public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
            return new ReactorInvocationHandler(target, dispatch, scheduler);
        }
    }
}
